import React, { useRef } from "react";

interface IFormState {
  state: any;
}

class FormStore<IFormState> {
  // [x: string]: {};
  // 存储每个Fields的数据
  store: { [key: string]: any } = {};
  // 存储Field组件实例
  fieldEntries: IField[] = [];
  // 存储form实例方法
  callbacks: any = {};

  setCallbacks = (newCallback: Function) => {
    this.callbacks = {
      ...this.callbacks,
      ...newCallback,
    };
  };

  registerFieldEntity = (Field: IField) => {
    this.fieldEntries.push(Field);
    return () => {
      this.fieldEntries.filter((f) => f !== Field);
      Reflect.deleteProperty(this.store, Field.props.name);
    };
  };

  getFieldsValue = () => {
    return {
      ...this.store,
    };
  };

  getFieldValue = (name: string) => {
    return this.store[name];
  };

  setFieldsValue = (newStore: { [key: string]: any }) => {
    // 1. 修改store
    this.store = {
      ...this.store,
      ...newStore,
    };

    // 2。更新组件

    this.fieldEntries.forEach((field) => {
      Object.keys(newStore).forEach((key) => {
        if (field.props.name === key) {
          field.onStoreChange();
        }
      });
    });
  };

  validate = () => {
    // 验证error
    const err: any[] = [];

    this.fieldEntries.forEach((field) => {
      if (Array.isArray(field.props.rules) && field.props.rules.length) {
        field.props.rules.forEach((rule) => {
          if (rule.required) {
            if (!this.store[field.props.name]) {
              let idx = err.findIndex((item) => {
                let name = Object.keys(item)[0]
                return name === field.props.name
              })
              if (idx !== -1) {
                err[idx][field.props.name] = rule.message;
              } else {
                err.push({
                  [field.props.name]: rule.message,
                });
              }
            }
          }
        });
      }
    });

    return err;
  };

  submit = () => {
    const { onFinish, onFinishFailed } = this.callbacks;

    let err = this.validate();
    if (err.length) {
      onFinishFailed(err, this.getFieldsValue);
    } else {
      onFinish(this.getFieldsValue());
    }
  };

  getForm = () => ({
    getFieldsValue: this.getFieldsValue,
    getFieldValue: this.getFieldValue,
    setFieldsValue: this.setFieldsValue,
    registerFieldEntity: this.registerFieldEntity,
    submit: this.submit,
    setCallbacks: this.setCallbacks,
  });
}

export default function useForm(form: IUseForm) {
  const formRef = useRef<IUseForm>();
  if (!formRef.current) {
    if (form) {
      formRef.current = form;
    } else {
      const formStore = new FormStore();
      formRef.current = formStore.getForm();
    }
  }
  return [formRef.current];
}
